﻿using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.Geodatabase;

namespace CanSWAT.ArcSWAT
{
    /// <summary>
    /// Used to read land use basic information from crop/urban table in SWAT2009.mdb or shc table in project database
    /// </summary>
    class LanduseSnowHoldingCapacity
    {
        private string _name = "";
        private string _code = "";
        private int _classification = -1;       //urban will be 0, crop will be from 1 to 7, 7 is tree
        private int _shc_convention_till = 0;   //snow holding capacity for conventional till
        private int _shc_no_till = 0;           //snow holding capacity for no till
        private bool _isUsedInFinalHRU = false;

        public static string FIELD_NAME_SHC_NAME = "NAME";
        public static string FIELD_NAME_SHC_CODE = "CODE";
        public static string FIELD_NAME_SHC_CLASSIFICATION = "CLASS";
        public static string FIELD_NAME_SHC_SHC_CONVENTIONAL = "SHC_CON";
        public static string FIELD_NAME_SHC_SHC_NO = "SHC_NO";

        /// <summary>
        /// get snow holding capacity based on classification
        /// </summary>
        /// <param name="classification"></param>
        /// <returns></returns>
        /// <remarks>Need to be revised in the future</remarks>
        private static int getSHCFromClassification(int classification)
        {
            if (classification == 0) return 10; //urban area
            if (classification == 7) return 500;
            else return 40;
        }

        /// <summary>
        /// get shc for no till from shc for conventional till
        /// </summary>
        /// <param name="conventionalTillSHC"></param>
        /// <returns></returns>
        /// <remarks>Need to be revised in the future</remarks>
        private static int getNoTillSHC(int classification, int conventionalTillSHC)
        {
            if (classification >= 1 && classification <= 6)
                return conventionalTillSHC * 2;
            else
                return conventionalTillSHC;
        }

        public static IFields DefaultFields
        {
            get
            {
                IFields fields = new FieldsClass();
                IFieldsEdit fieldsEdit = fields as IFieldsEdit;

                //string fields
                string[] stringFields = { FIELD_NAME_SHC_NAME, FIELD_NAME_SHC_CODE};
                foreach (string name in stringFields)
                {
                    IField nf = new FieldClass();
                    IFieldEdit f = nf as IFieldEdit;
                    f.Name_2 = name;
                    f.Type_2 = esriFieldType.esriFieldTypeString;
                    f.DefaultValue_2 = "";
                    f.AliasName_2 = name;

                    fieldsEdit.AddField(nf);
                }

                //integer fields
                string[] intFields = { FIELD_NAME_SHC_CLASSIFICATION, FIELD_NAME_SHC_SHC_CONVENTIONAL, FIELD_NAME_SHC_SHC_NO };
                foreach (string name in intFields)
                {
                    IField nf = new FieldClass();
                    IFieldEdit f = nf as IFieldEdit;
                    f.Name_2 = name;
                    f.Type_2 = esriFieldType.esriFieldTypeInteger;
                    f.DefaultValue_2 = -1;
                    f.AliasName_2 = name;

                    fieldsEdit.AddField(nf);
                }

                return fields;
            }
        }

        /// <summary>
        /// for reading from shc table in project database
        /// </summary>
        /// <param name="r"></param>
        public LanduseSnowHoldingCapacity(IRow r)
        {
            int nameIndex = r.Fields.FindField(FIELD_NAME_SHC_NAME);
            init(r.get_Value(nameIndex).ToString(),
                r.get_Value(nameIndex + 1).ToString(),
                Convert.ToInt32(r.get_Value(nameIndex + 2).ToString()),
                Convert.ToInt32(r.get_Value(nameIndex + 3).ToString()),
                Convert.ToInt32(r.get_Value(nameIndex + 4).ToString()));
        }

        public LanduseSnowHoldingCapacity(string name, string code, int classification)
        {
            int shc = getSHCFromClassification(classification);
            init(name, code, classification,
                shc, getNoTillSHC(classification,shc));
        }

        private void init(string name, string code, int classification, int shc_con, int shc_no)
        {
            _name = name;
            _code = code;
            _classification = classification;
            _shc_convention_till = shc_con;
            _shc_no_till = shc_no;
        }

        public void save2row(IRowBuffer r)
        {
            int nameIndex = r.Fields.FindField(FIELD_NAME_SHC_NAME);

            r.set_Value(nameIndex + 0, _name);
            r.set_Value(nameIndex + 1, _code);
            r.set_Value(nameIndex + 2, _classification);
            r.set_Value(nameIndex + 3, _shc_convention_till);
            r.set_Value(nameIndex + 4, _shc_no_till);
        }

        public void update(ITable t)
        {
            IQueryFilter qf = new QueryFilterClass();
            qf.WhereClause = string.Format("{0}='{1}'", FIELD_NAME_SHC_CODE,Code);
            ICursor updateCursor = t.Update(qf, false);
            try
            {
                IRow r = updateCursor.NextRow();
                if (r != null)
                {
                    int nameIndex = r.Fields.FindField(FIELD_NAME_SHC_NAME);

                    r.set_Value(nameIndex + 3, _shc_convention_till);
                    r.set_Value(nameIndex + 4, _shc_no_till);
                    updateCursor.UpdateRow(r);
                }   
            }
            finally
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(updateCursor);
            }
        }

        public string Name
        {
            get { return _name; }
        }

        public string Code
        {
            get { return _code; }
        }

        public int ConventionalTill
        {
            get { return _shc_convention_till; }
            set { _shc_convention_till = value; }
        }

        public int NoTill
        {
            get { return _shc_no_till; }
            set { _shc_no_till = value; }
        }

        public bool IsUsedInFinalHRU
        {
            get { return _isUsedInFinalHRU; }
            set { _isUsedInFinalHRU = value; }
        }

        public override string ToString()
        {
            return string.Format("{0}({1})",
                _name,_code);
        }

        public LanduseSnowHoldingCapacity Clone()
        {
            return this.MemberwiseClone() as LanduseSnowHoldingCapacity;
        }
    }
}
